#include "CAnimationEngine.h"
#include "CFrame.h"
#include <fstream>
#include <windows.h>
#include <vector>
using namespace std;
#include "SGD Wrappers/CSGD_TextureManager.h"


CAnimationEngine* CAnimationEngine::m_nInstance = NULL;


CAnimationEngine::CAnimationEngine(void)
{
	m_szRelativePathImage = "resource/graphics/";
	m_szRelativePathData = "resource/data/";
}

CAnimationEngine::~CAnimationEngine(void)
{
}

CAnimationEngine* CAnimationEngine::GetInstance()
{
	if(m_nInstance == NULL)
	{
		m_nInstance = new CAnimationEngine;
	}

	return m_nInstance;
}

void CAnimationEngine::Init(string szFilepath)
{
	m_szRelativePathData.append(szFilepath);
	ifstream in(m_szRelativePathData.c_str(), std::ios_base::binary);

	double VNumber = 0;
	in.read((char*)&VNumber, sizeof(double));
	int AnimCount = 0;;
	in.read((char*)&AnimCount, sizeof(int));

	for(int i = 0; i < AnimCount; ++i)
	{
		CAnimation* TempAnim = new CAnimation();
		
		char tempBuff[128] = {0};
		int length = 0;
		in.read((char*)&length, sizeof(int));
		in.read(tempBuff, sizeof(char));
		in.read(tempBuff, (sizeof(char) * length));
		TempAnim->SetTag(tempBuff);

		int lengthb = 0;
		char tempBuffb[128] = {0};

		in.read((char*)&lengthb, sizeof(int));
		in.read(tempBuffb, sizeof(char));
		in.read(tempBuffb, (sizeof(char) * lengthb));
		m_szRelativePathImage.append(tempBuffb);
		TempAnim->SetImageID(CSGD_TextureManager::GetInstance()->LoadTexture(m_szRelativePathImage.c_str()));

		int IsLooping = 0;
		in.read((char*)&IsLooping, sizeof(int));
		TempAnim->SetLooping(IsLooping);

		int nFrames = 0;
		in.read((char*)&nFrames, sizeof(int));
		TempAnim->SetTotalFrame(nFrames);

		for(int j = 0; j < nFrames; ++j)
		{

			CFrame* TempFrame = new CFrame();
			double tempDuration;
			in.read((char*)&tempDuration, sizeof(double));
			TempFrame->SetDuration((float)tempDuration);

			char szTrigger[128] = {0};
			in.read((char*)&length, sizeof(int));
			in.read(szTrigger, sizeof(char));
			in.read(szTrigger, (sizeof(char) * length));
			TempFrame->SetTrigger(szTrigger);

			RECT rTemp;
			int width = 0;
			int height = 0;

			in.read((char*)&rTemp.left, sizeof(int));
			in.read((char*)&rTemp.top, sizeof(int));
			in.read((char*)&width, sizeof(int));
			in.read((char*)&height, sizeof(int));
			rTemp.right = rTemp.left + width;
			rTemp.bottom = rTemp.top + height;

			TempFrame->SetImageRect(rTemp);

			
			in.read((char*)&rTemp.left, sizeof(int));
			in.read((char*)&rTemp.top, sizeof(int));
			in.read((char*)&width, sizeof(int));
			in.read((char*)&height, sizeof(int));
			rTemp.right = rTemp.left + width;
			rTemp.bottom = rTemp.top + height;

			TempFrame->SetCollRect(rTemp);

			POINT pTemp;
			in.read((char*)&pTemp.x, sizeof(int));
			in.read((char*)&pTemp.y, sizeof(int));

			TempFrame->SetAnchorX(pTemp.x);
			TempFrame->SetAnchorY(pTemp.y);

			in.read((char*)&pTemp.x, sizeof(int));
			in.read((char*)&pTemp.y, sizeof(int));

			TempFrame->SetArmX(pTemp.x);
			TempFrame->SetArmY(pTemp.y);

			TempAnim->AddFrame(TempFrame);
			//delete TempFrame;
		}
		std::pair<string, CAnimation*> TempPair;
		TempPair.first = TempAnim->GetTag();
		TempPair.second = TempAnim;

		m_mAnimations.insert(TempPair);
		//delete TempAnim;
	}
	in.close();
}

void CAnimationEngine::Update(CAnimationInfo& Info, float fElapsedTime)
{
	if(Info.GetPlaying() == false)
		return;

	map<string, CAnimation*>::iterator iter = m_mAnimations.find(Info.GetAnimation());

	if(iter == m_mAnimations.end())
		return;
	
	Info.SetTimer(Info.GetTimer() + fElapsedTime);

	if(Info.GetTimer() + 0.001 > (*iter).second->GetCurFrame(Info.GetCurFrame())->GetDuration())
	{
		if(Info.GetCurFrame() < (*iter).second->GetTotalFrame()-1)
		{
			Info.SetCurFrame(Info.GetCurFrame() + 1);
			Info.SetTimer(Info.GetTimer() - (*iter).second->GetCurFrame(Info.GetCurFrame())->GetDuration());
		}
		else
		{
			Info.SetCurFrame(0);
			Info.SetTimer(Info.GetTimer() - (*iter).second->GetCurFrame(Info.GetCurFrame())->GetDuration());
			
			if((*iter).second->GetLooping() == false)
			{
				Info.SetPlaying(true);
			}
		}
	}
}

void CAnimationEngine::Render(string szTag, int CurFrame, int PosX, int PosY, float scalex, float scaley)
{
	map<string, CAnimation*>::iterator iter = m_mAnimations.find(szTag);

	if(iter == m_mAnimations.end())
		return;
	
	(*iter).second->GetCurFrame(CurFrame);

	PosX -= ((*iter).second->GetCurFrame(CurFrame)->GetAnchorX() - (*iter).second->GetCurFrame(CurFrame)->GetImageRect().left);
	PosY -= ((*iter).second->GetCurFrame(CurFrame)->GetAnchorY() - (*iter).second->GetCurFrame(CurFrame)->GetImageRect().top);

	RECT tempRect = (*iter).second->GetCurFrame(CurFrame)->GetImageRect();


	CSGD_TextureManager::GetInstance()->Draw((*iter).second->GetImageID(), PosX, PosY, scalex, scaley, &(RECT)(*iter).second->GetCurFrame(CurFrame)->GetImageRect());

}

void CAnimationEngine::RemoveAllAnimations()
{
	//for(int i = 0; i < m_mAnimations.size() ; ++i)
	//{
	//	m_mAnimations[i]->DeleteFrames();
	//	delete m_mAnimations[i];
	//	m_mAnimations[i] = NULL;
	//}

	m_mAnimations.clear();
}

void CAnimationEngine::Shutdown()
{
	RemoveAllAnimations();
	if(m_nInstance)
	{
		delete m_nInstance;
		m_nInstance=NULL;
	}


}